/* @file           : usbd_audio_player.c
 * @brief          USB音频播放器核心实现
 *                 实现USB音频数据的接收和I2S输出（相同采样率版本）
 */
#if 1
#include "usb_audio_player.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

extern I2S_HandleTypeDef hi2s2;

/* 硬件配置常量 */
#define I2S_BUF_SAMPLES   (256)       // 缓冲区大小(256样本)
#define I2S_BUF_BYTES      (I2S_BUF_SAMPLES  *2)         // 音频缓冲区大小(512字节)

// 同步控制参数（优化版本）
#define BUFFER_TARGET_LEVEL  50    // 目标填充率(%)
#define ADJUST_THRESHOLD     10    // 提高调整阈值，减少微调频率
#define BASE_ADJUST_STEP     1     // 减小基础步长，降低失真
#define FINE_ADJUST_STEP     1     // 微调步长
#define NO_ADJUST_COUNT      5     // 增加防抖动计数，减少强制微调

// 新增进度条跳转相关参数
#define AUDIO_FRAME_SIZE     4     // 单帧大小（16bit双声道）
#define SEEK_RESET_THRESHOLD 32    // 跳转后重置阈值

// 全局变量定义
uint16_t audioOutputBuffer[I2S_BUF_BYTES    ];          // I2S输出音频缓冲区
uint32_t samplesInBuffer = 0;                    // USB缓冲区中的样本数量
uint16_t* usbAudioSourceBuffer = 0;              // USB音频数据源缓冲区指针
volatile int availableUsbSamples = 0;            // 可用的USB样本数量

// 位置跟踪与同步变量
uint32_t readPosition = 0;  // 当前读取位置
uint32_t lastReadPosition = 0;
int32_t syncErrorAccumulator = 0;
uint32_t frameCounter = 0;

// 同步状态变量
volatile int32_t g_last_fill_percent = 50;
volatile uint8_t g_no_adjust_cnt = 0;
volatile uint8_t g_seek_flag = 0;  // 进度条跳转标志
volatile int32_t g_seek_offset = 0;  // 跳转偏移量

// 调试状态变量
volatile uint8_t g_i2s_underflow_flag = 0;
volatile uint32_t g_i2s_tx_cnt = 0;
volatile uint32_t g_usb_write_pos;
volatile uint8_t g_i2s_error_flag = 0;

/* 立体声音频帧结构体 */
typedef struct {
    int16_t leftChannel;   // 左声道音频样本
    int16_t rightChannel;  // 右声道音频样本
} AudioFrameStereo;

/**
 * @brief  启动I2S传输
 */
void I2S_StartAudioOutput()
{
    // 启动I2S DMA传输
    HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t *)audioOutputBuffer, I2S_BUF_BYTES    );
}

/**
 * @brief  获取下一个音频样本（优化版本）
 */
AudioFrameStereo getNextAudioSample()
{
    AudioFrameStereo result = {0, 0};

    if(availableUsbSamples > 0 && usbAudioSourceBuffer && samplesInBuffer > 0)
    {
        // 处理进度条跳转
        if (g_seek_flag)
        {
            // 计算新的读取位置（帧对齐）
            int32_t new_pos = (readPosition + g_seek_offset) % samplesInBuffer;
            if (new_pos < 0) new_pos += samplesInBuffer;
            readPosition = new_pos;

            // 重置同步状态
            availableUsbSamples = (samplesInBuffer * BUFFER_TARGET_LEVEL) / 100;
            g_last_fill_percent = BUFFER_TARGET_LEVEL;
            g_no_adjust_cnt = 0;
            g_seek_flag = 0;
            g_seek_offset = 0;
        }

        // 样本读取（保持防越界）
        uint32_t safePosition = readPosition % samplesInBuffer;
        result.leftChannel = usbAudioSourceBuffer[safePosition * 2];
        result.rightChannel = usbAudioSourceBuffer[safePosition * 2 + 1];

        // 位置更新
        readPosition++;
        if(readPosition >= samplesInBuffer)
        {
            readPosition = 0;
        }
        availableUsbSamples--;
    }

    return result;
}

/**
 * @brief  音频初始化
 */
void AUDIO_Init(uint32_t AudioFreq, uint32_t Volume, uint32_t options)
{
    // 重置所有状态变量
    memset(audioOutputBuffer, 0, sizeof(audioOutputBuffer));
    samplesInBuffer = 0;
    usbAudioSourceBuffer = 0;
    availableUsbSamples = 0;
    readPosition = 0;
    frameCounter = 0;

    // 重置同步状态
    g_last_fill_percent = 50;
    g_no_adjust_cnt = 0;
    g_seek_flag = 0;
    g_seek_offset = 0;

    // 重置错误标志
    g_i2s_underflow_flag = 0;
    g_i2s_tx_cnt = 0;
    g_usb_write_pos = 0;
    g_i2s_error_flag = 0;

    I2S_StartAudioOutput();
    printf("AUDIO_Init: AudioFreq=%ld, Volume=%ld, options=%ld\n", AudioFreq, Volume, options);
}

/**
 * @brief  音频输出启动
 */
void AUDIO_OUT_Start(uint16_t* pBuffer, uint32_t Size)
{
    printf("AUDIO_OUT_Start: pBuffer=%p, Size=%ld\n", pBuffer, Size);

    samplesInBuffer = Size / 2;
    usbAudioSourceBuffer = pBuffer;
    // 初始位置设为缓冲区中间（保持兼容性）
    readPosition = samplesInBuffer / 2;
    availableUsbSamples = samplesInBuffer / 2;

    // 重置同步状态
    frameCounter = 0;
    g_no_adjust_cnt = 0;
    g_seek_flag = 0;
}

/**
 * @brief  USB音频数据周期回调（核心优化）
 */
void AUDIO_OUT_Periodic(uint16_t* pBuffer, uint32_t Size)
{
    if(!usbAudioSourceBuffer || samplesInBuffer == 0) return;

    // 1. 计算填充率与偏差（保持核心逻辑）
    uint32_t usbWritePos = (pBuffer - (uint16_t*)usbAudioSourceBuffer) / 2;
    g_usb_write_pos = usbWritePos;  // 更新全局USB写入位置
    int32_t bufferFill = (readPosition - usbWritePos + samplesInBuffer) % samplesInBuffer;
    int fillPercentage = (bufferFill * 100) / samplesInBuffer;
    int deviation = fillPercentage - BUFFER_TARGET_LEVEL;

    // 2. 优化的同步调整逻辑（减少失真）
    if(abs(deviation) >= ADJUST_THRESHOLD)
    {
        // 基础调整：使用更小的步长
        int adjustStep = (deviation > 0) ? -BASE_ADJUST_STEP : BASE_ADJUST_STEP;
        readPosition = (readPosition + adjustStep + samplesInBuffer) % samplesInBuffer;
        g_no_adjust_cnt = 0;
    }
    else if(g_no_adjust_cnt >= NO_ADJUST_COUNT)
    {
        // 减少强制微调频率，仅在必要时调整
        if(abs(deviation) > 2)  // 微小偏差不调整
        {
            int fineStep = (deviation > 0) ? -FINE_ADJUST_STEP : FINE_ADJUST_STEP;
            readPosition = (readPosition + fineStep + samplesInBuffer) % samplesInBuffer;
        }
        g_no_adjust_cnt = 0;
    }
    else
    {
        g_no_adjust_cnt++;
    }

    // 3. 修正可用样本数
    availableUsbSamples = bufferFill;
    frameCounter++;
}

/**
 * @brief  进度条跳转函数（新增核心功能）
 * @param  frame_offset: 帧偏移量（正数向前，负数向后）
 */
void AUDIO_SEEK(int32_t frame_offset)
{
    if(samplesInBuffer == 0) return;

    // 标记跳转状态，在getNextAudioSample中处理
    g_seek_offset = frame_offset;
    g_seek_flag = 1;

    // 暂停I2S避免跳转时播放异常
    HAL_I2S_DMAStop(&hi2s2);

    // 清空当前缓冲区（避免旧数据干扰）
    memset(audioOutputBuffer, 0, sizeof(audioOutputBuffer));

    // 重启I2S
    I2S_StartAudioOutput();
}

/**
 * @brief  I2S传输完成回调（后半缓冲区）
 */
void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
{
    if(availableUsbSamples < I2S_BUF_SAMPLES   / 4)
    {
        g_i2s_underflow_flag = 1;
    }

    // 填充后半缓冲区
    AudioFrameStereo* buffer = ((AudioFrameStereo*)audioOutputBuffer) + (I2S_BUF_BYTES     / 4);
    for(int k = 0; k < (I2S_BUF_BYTES     / 4); k++)
    {
        buffer[k] = getNextAudioSample();
    }

    g_i2s_tx_cnt++;
}

/**
 * @brief  I2S传输半完成回调（前半缓冲区）
 */
void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{
    if(availableUsbSamples < I2S_BUF_SAMPLES   / 4)
    {
        g_i2s_underflow_flag = 1;
    }

    // 填充前半缓冲区
    AudioFrameStereo* buffer = (AudioFrameStereo*)audioOutputBuffer;
    for(int k = 0; k < (I2S_BUF_BYTES     / 4); k++)
    {
        buffer[k] = getNextAudioSample();
    }

    g_i2s_tx_cnt++;
}

/**
 * @brief  I2S错误回调
 */
void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s)
{
    g_i2s_error_flag = 1;
}

/**
 * @brief  主循环调试监控
 */
void main_loop_debug_monitor(void)
{
    static uint32_t last_print_tick = 0;
    uint32_t current_tick = HAL_GetTick();

    if(current_tick - last_print_tick >= 200)
    {
        if(usbAudioSourceBuffer && samplesInBuffer > 0)
        {
            uint32_t usbWritePos = g_usb_write_pos;
            int32_t bufferFill = (readPosition - usbWritePos + samplesInBuffer) % samplesInBuffer;
            int fillPercentage = (bufferFill * 100) / samplesInBuffer;
            int deviation = fillPercentage - BUFFER_TARGET_LEVEL;
            printf("Sync: Fill=%d%%, Dev=%d, I2S_Cnt=%ld, Seek=%d\n",
                   fillPercentage, deviation, g_i2s_tx_cnt, g_seek_flag);
        }

        if(g_i2s_underflow_flag)
        {
            printf("Warn: I2S buffer underflow!\n");
            g_i2s_underflow_flag = 0;
        }

        last_print_tick = current_tick;
    }
}
#endif
